import React, { Component, createRef } from 'react'
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
import { fromJS, is } from 'immutable'

import { Scrollbars } from 'react-custom-scrollbars'
import { intl } from '../../../intl/intl'
import Button from '../../../component/button/Button'
import themeHOC from '../../common/themeHOC'
import wsHOC from '../../common/wsHOC'

import { formatContractPriceDecimal, formatDecimal, formatValue } from '../../../utils/dataUtils'

import { setOrderBidAskPrice } from '../../../redux/actions/tradeOrderBoardAction'
import { unsubscribeDepth, subscribeDepth, getBidAsk, setPollBidAskEnabled } from '../../../redux/actions/tradeBidAskAction'

import './bid-ask.less'

@connect(state => {
  return {
    currentContract: state.trade.market.get('currentContract'),
    bidList: state.trade.bidAsk.get('bidList'),
    askList: state.trade.bidAsk.get('askList'),
    market: state.trade.market.get('market'),
    showDealDetail: state.trade.dealDetail.get('showDealDetail')
  }
}, dispatch => {
  return bindActionCreators({
    unsubscribeDepth, subscribeDepth,
    setOrderBidAskPrice, getBidAsk
  }, dispatch)
})
@wsHOC(props => {
  props.subscribeDepth(props.currentContract)
}, props => {
  props.unsubscribeDepth(props.currentContract)
})
@themeHOC
class BidAsk extends Component {
  constructor (props) {
    super(props)
    this.scrollbar = createRef()
    this.scrollChange = this.scrollChangeHandler.bind(this)
    this.backHandicapClick = this.backHandicapClickHandler.bind(this)
    this.lastPriceShowType = 'middle'
  }

  componentDidMount () {
    this.scrollMiddle()
    this.props.getBidAsk()
  }

  shouldComponentUpdate (nextProps, nextState, nextContext) {
    const { bidList, askList, market, showDealDetail, currentContract } = this.props
    return !is(bidList, nextProps.bidList) ||
      !is(askList, nextProps.askList) ||
      !is(showDealDetail, nextProps.showDealDetail) ||
      !is(market, nextProps.market) ||
      !is(currentContract, nextProps.currentContract)
  }

  componentDidUpdate (prevProps, prevState, snapshot) {
    const { currentContract, unsubscribeDepth, subscribeDepth } = this.props
    if (formatValue(prevProps.currentContract, 'InstrumentID') !== formatValue(currentContract, 'InstrumentID')) {
      unsubscribeDepth(prevProps.currentContract)
      subscribeDepth(currentContract)
    }
  }

  componentWillUnmount () {
    setPollBidAskEnabled(false)
  }

  /**
   * 滚动到中间位置
   */
  scrollMiddle () {
    const scroll = this.scrollbar.current
    if (scroll) {
      const scrollHeight = scroll.getScrollHeight()
      const clientHeight = scroll.getClientHeight()
      scroll.scrollTop(scrollHeight / 2 - clientHeight / 2)
    }
  }

  backHandicapClickHandler () {
    this.scrollMiddle()
  }

  scrollChangeHandler () {
    const scroll = this.scrollbar.current
    const scrollHeight = scroll.getScrollHeight()
    const clientHeight = scroll.getClientHeight()
    const scrollTop = scroll.getScrollTop()
    if (scrollTop > scrollHeight / 2 - 14) {
      if (this.lastPriceShowType !== 'top') {
        this.lastPriceShowType = 'top'
        this.forceUpdate()
      }
    } else if (scrollTop < scrollHeight / 2 - clientHeight + 14) {
      if (this.lastPriceShowType !== 'bottom') {
        this.lastPriceShowType = 'bottom'
        this.forceUpdate()
      }
    } else {
      if (this.lastPriceShowType !== 'middle') {
        this.lastPriceShowType = 'middle'
        this.forceUpdate()
      }
    }
  }

  /**
   * 渲染最近价
   * @param close
   * @param change
   * @param position
   * @returns {*}
   */
  renderLastPrice (close, change, position) {
    const { currentContract } = this.props
    let className = 'trade-bid-ask-list-last-price'
    if (position) {
      className = `${className} trade-bid-ask-list-last-price-float`
    }
    return (
      <div
        position={position}
        datatype={change > 0 ? 'up' : change < 0 ? 'low' : ''}
        className={className}>
        <p>
          {formatContractPriceDecimal(currentContract, close)}
          <span
            className="trade-bid-ask-list-last-price-tag">
            {change > 0 ? '↑' : change < 0 ? '↓' : ''}
          </span>
        </p>
        {
          position &&
          <Button
            className="trade-bid-ask-list-last-price-reset-button"
            onClick={this.backHandicapClick}>
            {intl('back_handicap')}
          </Button>
        }
      </div>
    )
  }

  /**
   * 获取最大数量
   */
  getMaxVolume () {
    const { bidList, askList } = this.props
    let maxVolume = 0
    bidList.forEach(bid => {
      maxVolume = Math.max(maxVolume, +(bid.get('Volume') || 0))
    })
    askList.forEach(ask => {
      maxVolume = Math.max(maxVolume, +(ask.get('Volume') || 0))
    })
    return maxVolume
  }

  renderBid (maxVolume) {
    const { currentContract, bidList, setOrderBidAskPrice } = this.props
    let totalVolume = 0
    const domArray = []
    for (let i = 0; i < 30; i++) {
      const data = bidList.get(i)
      let volume = '--'
      if (data) {
        volume = +(data.get('Volume'))
        totalVolume += volume
      } else {
        totalVolume = '--'
      }
      const percent = volume / maxVolume * 100
      domArray.push(
        <li
          key={`bid${i}`}
          onClick={() => { setOrderBidAskPrice(data.get('Price')) }}
          className="trade-bid-ask-list-row-container">
          <i
            datatype="buy"
            className="trade-bid-ask-list-row-rate"
            style={{ width: `${percent}%` }}/>
          <span
            direction="buy"
            datatype="price"
            className="trade-bid-ask-list-row-item">
            {formatContractPriceDecimal(currentContract, (data ? data.get('Price') : '--'))}
          </span>
          <span
            datatype="volume"
            className="trade-bid-ask-list-row-item">
            {formatDecimal(volume)}
          </span>
          <span
            datatype="totalVolume"
            className="trade-bid-ask-list-row-item">
            {formatDecimal(totalVolume)}
          </span>
        </li>
      )
    }
    return (
      <ul className="trade-bid-ask-list-content">
        {domArray}
      </ul>
    )
  }

  renderAsk (maxVolume = 1) {
    const { currentContract, askList, setOrderBidAskPrice } = this.props
    let totalVolume = 0
    const domArray = []
    for (let i = 0; i < 30; i++) {
      const data = askList.get(i)
      let volume = '--'
      if (data) {
        volume = +data.get('Volume')
        totalVolume += volume
      } else {
        totalVolume = '--'
      }
      const percent = volume / maxVolume * 100
      domArray.unshift(
        <li
          key={`ask${i}`}
          onClick={() => { setOrderBidAskPrice(data.get('Price')) }}
          className="trade-bid-ask-list-row-container">
          <i
            datatype="sell"
            className="trade-bid-ask-list-row-rate"
            style={{ width: `${percent}%` }}/>
          <span
            direction="sell"
            datatype="price"
            className="trade-bid-ask-list-row-item">
            {formatContractPriceDecimal(currentContract, (data ? data.get('Price') : '--'))}
          </span>
          <span
            datatype="volume"
            className="trade-bid-ask-list-row-item">
            {formatDecimal(volume)}
          </span>
          <span
            datatype="totalVolume"
            className="trade-bid-ask-list-row-item">
            {formatDecimal(totalVolume)}
          </span>
        </li>
      )
    }
    return (
      <ul className="trade-bid-ask-list-content">
        {domArray}
      </ul>
    )
  }

  render () {
    const { theme, currentContract, market, showDealDetail } = this.props
    const bidAskMaxVolume = this.getMaxVolume()
    const change = market.get('Change')
    const close = formatValue(showDealDetail.get(0), 'Price')
    return (
      <div className={`trade-bid-ask-${theme}`}>
        <p
          datatype="single"
          className="trade-column-content-title">
          {intl('handicap')}
        </p>
        <div className="trade-bid-ask-list-row-container">
          <span
            datatype="price"
            className="trade-bid-ask-list-row-item">
            {intl('price')}({formatValue(currentContract, 'PriceCurrency')})
          </span>
          <span
            datatype="volume"
            className="trade-bid-ask-list-row-item">
            {intl('volume')}
          </span>
          <span
            datatype="totalVolume"
            className="trade-bid-ask-list-row-item">
            {intl('grand_total')}
          </span>
        </div>
        <div className="trade-bid-ask-list-container">
          {this.lastPriceShowType === 'top' && this.renderLastPrice(close, change, 'top')}
          <Scrollbars
            ref={this.scrollbar}
            className="trade-bid-ask-list-content"
            onScroll={this.scrollChange}>
            {this.renderAsk(bidAskMaxVolume)}
            {this.renderLastPrice(close, change)}
            {this.renderBid(bidAskMaxVolume)}
          </Scrollbars>
          {this.lastPriceShowType === 'bottom' && this.renderLastPrice(close, change, 'bottom')}
        </div>
      </div>
    )
  }
}

export default BidAsk
